Перейти к основному содержимому

5.05. Веб-разработка и интеграции

Разработчику Архитектору

Веб-разработка и интеграции

ASP.NET Core

MVC, Razor Pages, Web API
Middleware, DI, конфигурация

ASP.NET – технология для создания веб-приложений, веб-API, сервисов, работающих под Windows, Linux, macOS. Поддерживает MVC, Razor Pages, Web API, SignalR и другие подходы.

Как работает ASP.NET Core?

ASP.NET построен на основе Kestrel – кросс-платформенного веб-сервера. Он может быть запущен как самостоятельный процесс или за обратным прокси-сервером (например, Nginx или IIS).

ASP.NET: Запрос – бизнес-логика – результат.

Pipeline (конвейер обработки запроса) работает в следующем порядке:

  • запрос приходит к серверу (Kernel);
  • проходит через цепочку middleware: логирование, статические файлы, маршрутизация, авторизация;
  • выполняется контроллер/обработчик;
  • ответ отправляется клиенту.

Структура проекта ASP.NET:

Папка / ФайлОписание
Program.csТочка входа в приложение. Начиная с .NET 6, содержит конфигурацию сервисов и middleware pipeline (вместо Startup.cs).
Startup.cs (до .NET 6)Класс для настройки зависимостей (ConfigureServices) и конвейера обработки запросов (Configure). Использовался до появления упрощённого хостинга в .NET 6.
wwwroot/Папка для статических файлов: CSS, JavaScript, изображения и другие ресурсы, доступные напрямую через HTTP.
Controllers/Содержит классы контроллеров, отвечающих за обработку HTTP-запросов в архитектуре MVC или Web API.
Views/Хранит представления (view), используемые в MVC, написанные на языке Razor (.cshtml).
Pages/Содержит страницы в модели Razor Pages, где каждая страница представляет собой отдельный маршрут с кодом и разметкой.
Models/Папка для классов, представляющих данные приложения (модели предметной области, DTO, view models).
appsettings.jsonJSON-файл с конфигурацией приложения: строки подключения, параметры сервисов, пользовательские настройки. Поддерживает профили (например, appsettings.Development.json).

Компоненты ASP.NET

Middleware – ПО промежуточного слоя (потому и middle), которое обрабатывает HTTP-запросы и ответы. К примеру, это аутентификация, логирование, обработка ошибок, статические файлы. Каждый компонент работает последовательно, словно конвейер, получая HttpContext, выполняя код, останавливая цепочку или отправляя ответ.

Все middleware подключаются в методе app.Use() или app.Run() внутри Program.cs.

Пример:

app.Use(async (context, next) =>
{
Console.WriteLine("Перед выполнением других middleware");

await next(); // Передаёт управление дальше

Console.WriteLine("После выполнения других middleware");
});

Middleware выполняются в том порядке, в котором они добавлены:

app.UseRouting(); // Сначала маршрутизация
app.UseAuthentication(); // Затем аутентификация
app.UseAuthorization(); // Потом авторизация
app.UseEndpoints(endpoints => { ... }); // И только потом — обработка

Dependency Injection (DI) – встроенный механизм внедрения зависимостей. Это способ передачи зависимостей в класс без жёсткой привязки к конкретной реализации. В ASP.NET есть встроенный контейнер DI, который управляет временем жизни объектов и их зависимостями. Регистрация происходит в Program.cs через builder.Services.

Services – регистрируются в DI-контейнере и доступны в контроллерах и middleware.

Время жизниОписание
AddSingletonОдин и тот же экземпляр сервиса используется на протяжении всего жизненного цикла приложения. Создаётся при первом запросе и сохраняется до завершения работы приложения. Подходит для логгеров, кэширующих сервисов, глобальных конфигураций.
AddScopedОдин экземпляр сервиса создаётся на один HTTP-запрос (или сеанс). Все компоненты, участвующие в обработке одного запроса, получают один и тот же экземпляр. Используется, например, для контекста базы данных (DbContext) и сервисов, зависящих от состояния запроса.
AddTransientНовый экземпляр сервиса создается при каждом обращении к нему. Подходит для простых, не содержащих состояния служб, таких как валидаторы, форматтеры, отправщики уведомлений.

Пример регистрации:

builder.Services.AddSingleton<ILogService, FileLogService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddTransient<IMessageSender, EmailSender>();

Routing – маршруты, которые можно определять через атрибуты или явно в pipeline.

[ApiController]
[Route("[controller]")]
public class HelloController : ControllerBase
{
[HttpGet]
public string Get() => "Hello from API!";
}

Маршрутизация – это процесс определения того, какой код должен обработать HTTP-запрос. ASP.NET использует endpoint routing, где маршруты регистрируются отдельно от обработчиков:

  • URL анализируется (/home/index);
  • по таблице маршрутов определяется, какой контроллер и метод вызвать;
  • выполняется метод, возвращается результат.

MVC – Model (данные и логика), View (представление, обычно .cshtml), Controller (обработчик запросов).

Контроллеры – это классы, содержащие действия (actions). Выше был приведён пример ApiController.

Контроллеры тесно связаны с машрутизацией. Вот атрибуты маршрутизации:

АтрибутОписание
[Route]Задаёт пользовательский маршрут для контроллера или действия; поддерживает шаблоны и токены (например, [Route("api/[controller]/[action]")])
[HttpGet] [HttpPost]Ограничивает действие определённым HTTP-методом (GET, POST и др.); часть набора атрибутов маршрутизации
[ApiController]Применяется к контроллеру API и включает поведение по умолчанию: автоматическая модельная привязка из тела, ответы 400 при ошибках валидации, обязательные атрибуты привязки
[FromQuery]< [FromBody]Указывает источник параметров: из строки запроса (query string) или из тела запроса (JSON, XML)

Razor Pages – упрощённая модель, где каждая страница – отдельный класс + .cshtml-файл. Razor – это шаблонизатор, который позволяет встраивать C# в HTML.

Синтаксис Razor

СинтаксисОписание
@model MyNamespace.MyModelОбъявляет тип модели, используемой в представлении (строго типизированное представление)
@using MyNamespaceПодключает пространство имён в текущем представлении
@{ ... }Блок кода на C#, используется для объявления переменных, циклов, условий
@if (...) { ... }Условная логика в разметке
@for (...) { ... }Цикл в представлении
@Html.Raw(...)Выводит строку как неэкранированный HTML (внимание: потенциальный риск XSS)
@Url.Action(...)Генерирует URL к указанному действию контроллера
@await Component.InvokeAsync(...)Асинхронный вызов компонента представления (view component)
@section Scripts { ... }Определяет секцию скриптов, которая будет вставлена в соответствующее место в _Layout.cshtml
@helper MyHelper(...) { ... }Определение пользовательского вспомогательного метода (устарело, не поддерживается в Razor Pages)

Элементы Razor

ЭлементОписание
@pageДиректива, указывающая, что файл — это Razor Page, а не MVC-представление; активирует обработку как независимой конечной точки
_Layout.cshtmlОсновной шаблон страницы, обеспечивающий единое оформление (header, footer, меню); используется через @layout
_ViewStart.cshtmlФайл, выполняемый перед каждым представлением; обычно задаёт общий Layout или общие переменные
Partial ViewsЧастичные представления (.cshtml) для повторного использования UI-фрагментов (например, формы, карточки); включаются через @Html.Partial() или <partial> Tag Helper
Tag HelpersКомпоненты, расширяющие стандартные HTML-теги серверной логикой (например, asp-controller, asp-action, asp-for); делают разметку чище и ближе к HTML

Tag Helpers позволяют расширять HTML-элементы возможностями C#. Например:

<a asp-controller="Home" asp-action="Index">Главная</a>
<form asp-action="SubmitForm" method="post">
<input asp-for="Name" />
<span asp-validation-for="Name"></span>
</form>

Страница (Page) — это класс, производный от System.Web.UI.Page. Каждая .aspx-страница компилируется в объект этого класса при выполнении запроса. Она управляет жизненным циклом, обработкой данных, рендерингом HTML и взаимодействием с пользователем. Когда браузер запрашивает .aspx файл, IIS передаёт управление ASP.NET, который создаёт экземпляр класса Page, вызывает нужные события жизненного цикла и генерирует HTML, который отправляется обратно клиенту.

Типы страниц бывают разными:

  • Обычная (aspx) — это самостоятельная страница с полной разметкой.
  • Мастер-страница (.master) - шаблон, задающий общий вид сайта (например, шапка, меню, футер). Позволяет создавать согласованный интерфейс.
  • Контентная страница использует мастер-страницу и заполняет её содержимым через ContentPlaceHolder.

Пользовательский элемент управления (ascx) это повторно используемый UI-компонент (например, кастомный хэдер или карточка товара).

Элементы управления (Controls) — это серверные компоненты, которые можно использовать на странице и программировать на C#. Они работают на стороне сервера, имеютс свой собственный жизненный цикл и автоматически сохраняют своё состояние, могут быть статичными (Label) или динамическими (TextBox, GridView, Button):

  • HTML-контролы (<div>)работают как обычный HTML, но доступны на сервере.
  • Веб-контролы (TextBox, Button) являются удобными, богатыми функциями, которые автоматически управляют состоянием.
  • Пользовательские контролы — это как раз пользовательские элементы управления.
  • Серверные контролы (Calendar, AdRotator) являются готовыми решениями от Microsoft.

Элементы управления выстраиваются в дерево элементов (Control Tree) при инициализации, словно DOM.

ViewState — это состояние страницы, механизм сохранения состояния элементов управления между PostBack'ами. Хранится в скрытом поле (__VIEWSTATE) на странице в виде закодированной строки. Это сохраняет значение текстовых полей, выбора в списке, и позволяет не перезагружать данные при каждом PostBack'е.

PostBack — это механизм, при котором браузер отправляет запрос на ту же самую страницу , с которой он был вызван (в отличие от GET-запроса или перехода на другую страницу). Пользователь взаимодействует с элементом управления (например, нажимает кнопку). JavaScript (__doPostBack) запускает форму с method="post" на эту же страницу. Сервер получает запрос, создаёт экземпляр страницы, восстанавливает её состояние (ViewState), обрабатывает событие. Страница снова рендерится и отправляется обратно браузеру.

Такое можно наблюдать для элементов Button, DropDownList, CheckBox, LinkButton, ImageButton. Используйте IsPostBack, чтобы не выполнять лишнюю инициализацию. Для динамических частей страницы применяйте UpdatePanel - механизм частичного PostBack (когда пользователь нажимает на кнопку, обновляется только содержимое панели без полной перезагрузки страницы).

Кроме PostBack, есть ещё Cross-Post, когда запрос отправляется на другую страницу, и Redirect - перенаправление, когда браузер загружает новую страницу.

Рендеринг — это финальный этап жизненного цикла, когда ASP.NET преобразует все элементы управления в HTML, который отправляется браузеру. Каждый контрол имеет метод Render(), который выводит свой HTML.

Инициализация происходит на этапе Init. На этом этапе создаются все элементы управления, присваиваются начальные свойства и происходит связь с родительской страницей. Если создавать элементы динамически (в коде), то лучше делать это именно на этапе Init, чтобы они участвовали во всех последующих этапах.

Страница в ASP.NET имеет свой жизненный цикл - последовательность этапов, через которые проходит веб-страница при обработке запроса от клиента (браузера). Каждый этап вызывает определённые события, на которые можно подписаться и выполнять пользовательский код.

Событие страницыОписание
PreInitПервое событие жизненного цикла. Можно задавать динамическую тему, мастер-страницу или создавать динамические контролы.
InitИнициализация элементов управления. Все контролы создаются и получают свои начальные свойства.
InitCompleteУказывает на завершение этапа инициализации. Доступны все контролы, можно выполнять действия, требующие полной инициализации.
LoadViewStateВосстановление состояния страницы из ViewState, если запрос является PostBack.
LoadPostDataОбработка данных формы: контролы, реализующие IPostBackDataHandler, обновляют своё состояние (например, текст в TextBox). Выполняется для каждого контрола отдельно.
PreLoadВызывается перед событием Load. Может использоваться для выполнения логики, которая должна быть до основной загрузки.
LoadОсновной этап загрузки страницы. Здесь обычно размещается бизнес-логика, привязка данных, взаимодействие с элементами управления.
LoadCompleteВызывается после завершения Load. Подходит для завершающих действий, например, запуск асинхронных операций.
PreRenderПоследняя возможность изменить содержимое страницы или контролов перед рендерингом. Все данные уже загружены.
PreRenderCompleteУказывает, что этап PreRender завершён. Используется редко, часто внутренними механизмами платформы.
SaveStateCompleteПосле сохранения ViewState и ControlState. Подходит для операций, которые не должны влиять на состояние страницы.
UnloadПоследнее событие жизненного цикла. Используется для освобождения внешних ресурсов (файлов, соединений). Не рекомендуется для работы с контролами или HTTP-контекстом.
вход в ASP, авторизация и аутентификация, управление статусом входа в ASP и его элементы.

ASP.NET поддерживает надежные элементы управления входом для веб-приложений, не требующие никакого программного кодирования. Элемент управления LoginStatus — очень простой элемент управления, все, что он делает, — отображает ссылку, которая отличается в зависимости от того, вошел ли пользователь в систему или нет. Если пользователь вошел в систему, он отображает ссылку LogOut и наоборот.

Он поддерживает несколько свойств, LogOutAction можно использовать для указания того, что происходит, когда пользователь нажимает на LogOutLink, а параметры — Redirect, RedirectToLoginPage, Refresh. Если мы устанавливаем Redirect, то мы должны установить другое свойство LogOutPage Url, на которое перенаправляется пользователь после выхода из веб-сайта.

WCF

Веб-сервисы в C#

WCF (Windows Communication Foundation)
Кратко: что такое, когда использовать
Сервисы, контракты, привязки
WCF
System.ServiceModel, System.ServiceModel.Channels, Binding – основы Windows Communication Foundation.
автогенерируемый прокси-класс WCF.

Интеграции

REST, gRPC, SOAP в C#
Работа с внешними API в C#

Планирование задач (Quartz.NET)
Cron – формат расписания (0 0 1 */10 * * – каждые 10 дней в 1:00).

Quartz.NET – библиотека для планирования задач в .NET.

Job, Trigger, Scheduler – ключевые понятия Quartz.

Потоки данных
Подпоток (Substream) – часть основного потока интеграции (например, шаг ETL).

Интеграционный поток – процесс обмена данными между системами.

OutputIntegrationStream<TModel, TResponse> – пример абстракции для исходящих данных.

Работа с моделями
ExportRepository<TModel> – репозиторий для выборки данных перед отправкой.

ImportRepository<TModel> – для сохранения полученных данных.

Обработка моделей – маппинг, валидация, сериализация.

Сессии интеграции
Открытие/закрытие сессии – аутентификация, получение ID сессии.

Интеграционная авторизация – токены, Basic Auth, OAuth и т.д.

Endpoint – настройка адресов (appsettings.json, DI).

Обработка ответов
Switch/case – ветвление логики на основе кодов ответа.

Импорт данных – обработка входящих данных через подпотоки.

protected abstract void – шаблон "Template Method" для кастомизации.